

package hotgammon.common;

import java.util.HashMap;
import java.util.Map;

public class GameImpl implements Game {
    private Color playerInTurn; /* The color of the player currently in turn */
    private Map<Location, Color> locationColors; /* Map from Locations to colors */
    private Map<Location, Integer> locationCount; /* Map from Locations to checker count */
    private int turn = 0; /* The current turn */
    private int movesLeft; /* Moves left in the current turn */
    private int[][] rolls = {{5,6}, {1,2}, {3,4}}; /* The dice-rolls available in alpha-mon */
    
    private WinnerStrategy winnerStategy;
    
    /** Reset the entire game to start from scratch. 
       * No player is in turn, and the game awaits a
       * call to nextTurn to start a game.
       */
    public void newGame(WinnerStrategy winnerStrategy) {
    	this.winnerStategy = winnerStrategy;
    	
        playerInTurn = Color.NONE;
        locationColors = new HashMap<Location, Color>();
        locationCount = new HashMap<Location, Integer>();
        
        //We update the two maps with the initial checker configuration
        locationColors.put(Location.R1, Color.BLACK);
        locationCount.put(Location.R1, 2);
        locationColors.put(Location.B1, Color.RED);
        locationCount.put(Location.B1, 2);
        locationColors.put(Location.B6, Color.BLACK);
        locationCount.put(Location.B6, 5);
        locationColors.put(Location.R6, Color.RED);
        locationCount.put(Location.R6, 5);
        locationColors.put(Location.B12, Color.RED);
        locationCount.put(Location.B12, 5);
        locationColors.put(Location.R12, Color.BLACK);
        locationCount.put(Location.R12, 5);
        locationColors.put(Location.R8, Color.RED);
        locationCount.put(Location.R8, 3);
        locationColors.put(Location.B8, Color.BLACK);
        locationCount.put(Location.B8, 3);
    }

    public void nextTurn() {
        turn++; // Increment the turn count 
        movesLeft = 2; // reset moves left
        if (playerInTurn == Color.BLACK) {
            playerInTurn = Color.RED;
        } else {
            playerInTurn = Color.BLACK;
        }
    }
    
    public boolean move(Location from, Location to) {
        if (movesLeft == 0) return false; // No move is allowed
        if (getColor(from) != playerInTurn) return false; // Trying to move an oppenents checker
        if (to == Location.B_BAR || to == Location.R_BAR // Trying to move to places we don't support
            || to == Location.R_BEAR_OFF || to == Location.B_BEAR_OFF) {
                return false;
            }
        
        if (getColor(to) != playerInTurn && getCount(to) > 0) return false; // Trying to move to a location occupied by the opponent
        
        if (!locationCount.containsKey(to)) { // This location has not been used before, hence we initialize its count
            locationCount.put(to, 0);
        }
        if (!locationColors.containsKey(to)) { //T his location is not colored, hence we color it
            locationColors.put(to, playerInTurn);
        }
        locationCount.put(from, locationCount.get(from) - 1); // Decrement the count of checker in the from location
        if (getCount(from) == 0) { // If the checker count in from is 0 remove its color.
            locationColors.put(from, Color.NONE);
        }
        locationCount.put(to, locationCount.get(to) + 1); // Increment the count of the to location
        movesLeft--; // Decrement movesLeft
        return true; 
    }

    public Color getPlayerInTurn() {
        return playerInTurn;
    }

    public int getNumberOfMovesLeft() { 
        return movesLeft; 
    }

    public int[] diceThrown() { 
        return this.rolls[turn%3]; 
    }

    public int[] diceValuesLeft() { 
        if (movesLeft == 2) return diceThrown();
        if (movesLeft == 1) return new int[]{diceThrown()[1]};
        return new int []{}; 
    }

    public Color winner() {
        //if (turn == 6) return Color.RED;
        //return Color.NONE; 
    	return winnerStategy.winner(turn, locationCount);
    }

    public Color getColor(Location location) { 
        if (!locationColors.containsKey(location)) return Color.NONE;
        return this.locationColors.get(location);
    }

    public int getCount(Location location) {
        if (this.locationCount.containsKey(location)) {
            return this.locationCount.get(location);   
        } else {
            return 0;
        }
    }
}
